package database;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import log.Log;

public class Storage implements ChangeListener, Serializable {

	private static final long serialVersionUID = -7396237470618509102L;
	private List<Individual> individuals = new ArrayList<Individual>();
	private static Storage storage;
	private File file;

	public Storage(File file) {
		this.file = file;
		try {
			readFromFile();
		} catch (IOException e) {
		}
	}

	public int getNextRecordID() {
		List<Integer> takenIDs = new ArrayList<Integer>();
		for (Individual ind : individuals) {
			if (ind instanceof Patient) {
				for (Record r : ((Patient) ind).getRecords()) {
					takenIDs.add(r.getID());
				}
			}
		}
		Collections.sort(takenIDs);
		int i = 0;
		for (; i < takenIDs.size(); i++) {
			if (takenIDs.get(i) != i) {
				return i;
			}
		}
		return i;
	}

	public void readFromFile() throws IOException {
		try {
			Log.log(Log.LOG_INFO, "Reading database from " + file);
			if (file.createNewFile()) {
				Log.log(Log.LOG_INFO, file + " did not exist and was created.");
				return;
			}
			ObjectInputStream inStream = new ObjectInputStream(
					new FileInputStream(file));
			individuals.addAll((List<Individual>) inStream.readObject());
			inStream.close();
			Log.log(Log.LOG_INFO, "Imported database successfully.");
			return;
		} catch (ClassCastException e) {
			Log.log(Log.LOG_ERROR, file + " corrupt!");
		} catch (ClassNotFoundException e) {
			Log.log(Log.LOG_ERROR, file + " corrupt!");
		}
		Log.log(Log.LOG_ERROR, "Couldn't import database from " + file + ".");
	}

	public void saveToFile() {
		try {
			ObjectOutputStream outStream = new ObjectOutputStream(
					new FileOutputStream(file));
			outStream.writeObject(individuals);
			outStream.flush();
			outStream.close();
		} catch (Exception e) {
			Log.log(Log.LOG_EXCEPTION, e.getMessage());
		}
	}

	public List<Individual> getIndividuals() {
		return individuals;
	}

	public Individual getIndividual(String name) {
		for (Individual ind : individuals) {
			if (ind.name.equals(name))
				return ind;
		}
		return null;
	}

	public void addIndividual(Individual ind) {
		ind.addChangeListener(this);
		individuals.add(ind);
		Log.log(Log.LOG_INFO, "Added user " + ind.getName() + " to database.");
		saveToFile();
	}

	public void change(Record record) {
		Log.log(Log.LOG_INFO, "Record " + record.getID()
				+ " was altered or removed.");
		saveToFile();
	}

}
